package com.codefish.framework.spring.aop.framework;

import com.codefish.framework.spring.aop.IMethodMatcher;
import com.codefish.framework.spring.aop.support.AopUtils;
import com.codefish.framework.spring.core.utils.ClassUtils;
import lombok.Getter;
import lombok.Setter;
import org.aopalliance.intercept.MethodInterceptor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Jdk动态代理支持
 *
 * @author <a href='https://gitee.com/hzf2281'>codefish</a>
 * @version 1.0.0
 * @since 2022/10/14 下午 02:48
 */
@Getter
@Setter
public class JdkDynamicAopProxy implements IAopProxy, InvocationHandler {

    private AdviseSupport adviseSupport;


    public JdkDynamicAopProxy(AdviseSupport adviseSupport) {
        this.adviseSupport = adviseSupport;
    }


    @Override
    public Object getProxy() {
        return Proxy.newProxyInstance(ClassUtils.getDefaultClassLoader(), adviseSupport.getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (AopUtils.isEqualsMethod(method)) {
            return equals(args[0]);
        }

        if (AopUtils.isHashCodeMethod(method)) {
            return hashCode();
        }
        //获得被代理对象
        Object target = adviseSupport.getTargetResource().getTarget();

        IMethodMatcher methodMatcher = adviseSupport.getMethodMatcher();
        if (methodMatcher != null && methodMatcher.matches(method, adviseSupport.getTargetResource().targetClass())) {
            MethodInterceptor methodInterceptor = adviseSupport.getMethodInterceptor();
            return methodInterceptor.invoke(new ReflectiveMethodInvocation(target, method, args));
        }

        return method.invoke(target, args);
    }

    /**
     * 重写hashcode方法
     */
    @Override
    public int hashCode() {
        return JdkDynamicAopProxy.class.hashCode() * 13 + adviseSupport.getTargetResource().hashCode();
    }

    /**
     * 重写equals方法
     */
    @Override
    public boolean equals(Object other) {
        if (other == null) {
            return false;
        }
        if (other == this) {
            return true;
        }
        JdkDynamicAopProxy otherAopProxy;
        if (other instanceof JdkDynamicAopProxy) {
            otherAopProxy = (JdkDynamicAopProxy) other;
        } else {
            InvocationHandler handler;
            try {
                handler = Proxy.getInvocationHandler(other);
            } catch (Exception e) {
                //如果比较的other对象不是一个代理对象，返回false
                return false;
            }
            if (!(handler instanceof JdkDynamicAopProxy)) {
                return false;
            }
            otherAopProxy = (JdkDynamicAopProxy) handler;
        }
        return AopUtils.equalInProxy(this.adviseSupport, otherAopProxy.getAdviseSupport());
    }
}
